package cn.conac.rc.gateway.modules.user.rest;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;

import cn.conac.rc.framework.utils.IpUtils;
import cn.conac.rc.framework.utils.StringUtils;
import cn.conac.rc.gateway.base.ResultPojo;
import cn.conac.rc.gateway.modules.user.entity.OuserEntity;
import cn.conac.rc.gateway.modules.user.entity.RoleEntity;
import cn.conac.rc.gateway.modules.user.entity.UserAreaEntity;
import cn.conac.rc.gateway.modules.user.entity.UserEntity;
import cn.conac.rc.gateway.modules.user.entity.UserExtEntity;
import cn.conac.rc.gateway.modules.user.service.UserService;
import cn.conac.rc.gateway.modules.user.vo.UserInfoVo;
import cn.conac.rc.gateway.security.UserUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import jxl.Cell;
import jxl.Range;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

@RestController
@RequestMapping(value="sys/")
@Api(tags="用户信息接口", description="用户信息")
public class ImportFileController {

    @Autowired
    UserService userService;
    
	/**
	 * 文件名长度限制
	 */
	@Value("${importFile.name.maxlength}")
	private int nameMaxlength;

	/**
	 * 允许导入文件后缀
	 */
	@Value("${importFile.allow.suffix}")
	private String allowSuffix;

	/**
	 * 文件最大值限制
	 */
	@Value("${importFile.max.volume}")
	private int maxVolume;
	
	/**
	 * 导入文件支持的行数
	 */
	@Value("${importFile.max.rows}")
	private int maxRows;
	
	/**
	 * 用户导入的初始密码
	 */
	@Value("${user.passwd.init}")
	private String initPasswd;
	
	/**
	 * 用户最后一次登录初始IP
	 */
	@Value("${user.last.login.ip.init}")
	private String initLastLoginIp;
	
	/**
	 * 导入用户的最大长度
	 */
	@Value("${user.fullName.maxLength}")
	private int fullNameMaxLen;
	
	/**
	 * 导入所属科室的最大长度
	 */
	@Value("${user.deptName.maxLength}")
	private int deptNameMaxLen;
	


	@ApiOperation(value = "用户信息文件导入", httpMethod = "POST", response = JSONObject.class, notes = "用户信息文件导入")
	@RequestMapping(value = "users/file/import", method = RequestMethod.POST)
	public Object cudImportUserInfoByExcel(HttpServletRequest request, HttpServletResponse response,
			@ApiParam(value = "导入文件对象", required = true) @RequestBody MultipartFile file){

		// 返回结果result定义
		ResultPojo resultInfo = new ResultPojo();
		if(StringUtils.isBlank(UserUtils.getCurrentUser().getOrgId())) {
			 resultInfo.setCode(ResultPojo.CODE_FAILURE);
	         resultInfo.setMsg("未绑定部门库错误");
	       	 resultInfo.setResult("当前用户没有绑定部门库，不能进行导入账号操作，请先为该用户绑定部门库");
	       	 return resultInfo;
		}
		// 上传文件的校验
		String msg = this.checkFileProperties(file,0,0,null);
		if(StringUtils.isNotBlank(msg)){
			resultInfo.setCode(ResultPojo.CODE_FAILURE);
			resultInfo.setMsg(msg);
			return resultInfo;
		}

		 List<UserInfoVo> userInfoVoList = new ArrayList<UserInfoVo>();
    	 // 将文件内容封装成UserInfoVo的list并检查输入对数据是否满足指定要求
		InputStream inputStreamFile = null;
		Workbook wb =null;
	
	   try {
			inputStreamFile = file.getInputStream();
			wb = Workbook.getWorkbook(inputStreamFile);
		} catch (BiffException e) {
			//e.printStackTrace();
			 resultInfo.setCode(ResultPojo.CODE_FAILURE);
	         resultInfo.setMsg("文件格式错误");
	       	 resultInfo.setResult("所选择的文件不是excel格式或者暂不支持excel高版本");
	       	 return resultInfo;
		} catch (IOException e) {
			 //e.printStackTrace();
			 resultInfo.setCode(ResultPojo.CODE_FAILURE);
	         resultInfo.setMsg("文件读取错误：" + e.getMessage() );
	       	 resultInfo.setResult(null);
	       	 return resultInfo;
		}
		Sheet sheet = wb.getSheet(0);
		int rows = sheet.getRows();
		if(rows > maxRows ) {
			resultInfo.setCode(ResultPojo.CODE_FAILURE);
            resultInfo.setMsg("文件内容错误");
       	    resultInfo.setResult("对不起，目前支持最大的导入数量为每次"+ maxRows +"条，烦请分多次导入");
       	    return resultInfo;
		}
		// 判断是否使用了提供的模板
		Range[] range = sheet.getMergedCells();
		if(range.length != 1) {
			resultInfo.setCode(ResultPojo.CODE_FAILURE);
            resultInfo.setMsg("模板使用错误");
       	    resultInfo.setResult("导入用户信息的文件模板使用不正确，烦请使用提供的导入模板");
       	    return resultInfo;
		}
		if(StringUtils.isEmpty(range[0].getTopLeft().getContents())){
			resultInfo.setCode(ResultPojo.CODE_FAILURE);
            resultInfo.setMsg("模板使用错误");
       	    resultInfo.setResult("导入用户信息的文件模板使用不正确，烦请使用提供的导入模板");
       	    return resultInfo;
		}
		Cell fullNameColCell = sheet.getCell(0, 1);
		Cell deptNameColCell = sheet.getCell(1, 1);
		Cell roleNameColCell = sheet.getCell(2, 1);
		if(!("姓名".equals(fullNameColCell.getContents().trim()) 
			   && "所属处（科）室".equals(deptNameColCell.getContents().trim()))
			   && "角色".equals(roleNameColCell.getContents().trim())) {
			resultInfo.setCode(ResultPojo.CODE_FAILURE);
            resultInfo.setMsg("模板使用错误");
       	    resultInfo.setResult("导入用户信息的文件模板使用不正确，烦请使用提供的导入模板");
       	    return resultInfo;
		}
		
		UserInfoVo userInfoVo = null;
		UserExtEntity userExtEntity =null;
		UserEntity userEntity =null;
		UserAreaEntity userAreaEntity =null;
		OuserEntity ouserEntity =null;
		JSONObject retUserInfoJson = null;
		Map<String, List<String>> errorMap = new HashMap<String,List<String>>();
		List<String> errorList = new ArrayList<String>();
		errorMap.put("error", errorList);	
		// 遍历导入文件的内容
		for(int i=0; i < rows -2 ; i++) {
			
			userInfoVo = new UserInfoVo();
			
			// **************用户扩展信息实体**************
			userExtEntity = new UserExtEntity();
			// 取得编制域名的姓名
            Cell fullNameCell = sheet.getCell(0, i+2);
            Cell deptNameCell = sheet.getCell(1, i+2);
            Cell roleNameCell = sheet.getCell(2, i+2);
            if(StringUtils.isEmpty(fullNameCell.getContents()) 
            		&& StringUtils.isEmpty(deptNameCell.getContents())
            		&& StringUtils.isEmpty(roleNameCell.getContents())
            		) {
            	continue;
            }
            if(StringUtils.isEmpty(fullNameCell.getContents())) {
            	errorMap.get("error").add("第" + (i+3) + "行的[姓名]为空" );
            }
            
            if(StringUtils.isNotBlank(fullNameCell.getContents())) {
            	 // 判断所输入的姓名是否为汉字
            	Boolean isChineseStr = StringUtils.checkIsChineseStr(fullNameCell.getContents());
            	if(!isChineseStr){
            		errorMap.get("error").add("第" + (i+3) + "行的[姓名]不全是中文字符" );
            	}
            	// 判断所输入的姓名是否超过了指定的长度
            	if(fullNameCell.getContents().length() > fullNameMaxLen) {
            		errorMap.get("error").add("第" + (i+3) + "行的[姓名]最大允许输入的长度为"+ fullNameMaxLen );
            	}
            }
			// 取得编制域名的姓名
            userExtEntity.setFullName(fullNameCell.getContents());
            // 设置绑定部门
            userExtEntity.setOrgId(Integer.valueOf(UserUtils.getCurrentUser().getOrgId()));
            // 设置用户类别 TODO 支持委办局导入时应该要修改
            userExtEntity.setUserType(UserExtEntity.USER_TYPE_BB);
            userInfoVo.setUserExtEntity(userExtEntity);
            
            // **************用户基本信息实体**************
			userEntity = new UserEntity();
			 // 取得编制域名的所属科室
            if(StringUtils.isEmpty(deptNameCell.getContents())) {
            	errorMap.get("error").add("第" + (i+3) + "行的[所属科室]为空" );
            }
            if(StringUtils.isNotBlank(deptNameCell.getContents())) {
	           	// 判断所输入的所属科室是否超过了指定的长度
	           	if(deptNameCell.getContents().length() > deptNameMaxLen) {
	           		errorMap.get("error").add("第" + (i+3) + "行的[所属处（科）室]最大允许输入的长度为"+ deptNameMaxLen );
	           	}
           }
            // 取得角色名称信息
            if(StringUtils.isEmpty(roleNameCell.getContents())) {
            	errorMap.get("error").add("第" + (i+3) + "行的[角色]为空" );
            }
            if(StringUtils.isNotBlank(roleNameCell.getContents())) {
	           	// 判断所输入的角色是否合理
	           	if("综合管理员".equals(roleNameCell.getContents().trim()) 
	           		|| "三定管理员".equals(roleNameCell.getContents().trim()) 
	           		|| "清单管理员".equals(roleNameCell.getContents().trim()) 
	           		|| "信息查询人员".equals(roleNameCell.getContents().trim()) ) {
	           		// do nothing
	           	} else {
	           		errorMap.get("error").add("第" + (i+3) + "行的[角色]内容不正确，只允许输入（综合管理员、三定管理员、清单管理员、信息查询人员）四种类型角色" );
	           	}
           }
            userEntity.setDeptName(deptNameCell.getContents());
            userEntity.setGroupId(1);
			userEntity.setRegisterTime(new Date());
			// 设置注册用户ID
		    userEntity.setRegisterUserId(Integer.valueOf(UserUtils.getCurrentUser().getId()));
			// 设置注册用户IP
			userEntity.setRegisterIp(IpUtils.getRemoteAddr(request));
			userEntity.setLastLoginTime(new Date());
			userEntity.setLastLoginIp(initLastLoginIp);
			userEntity.setLoginCount(0);
			//编制域名
			userEntity.setIsOrgDomain(UserEntity.BZ_DOMAIN_NANE_FLAG);
			userEntity.setIsAdmin(1);
			userEntity.setIsDeleted(0);
			userEntity.setIsViewonlyAdmin(0);
			userEntity.setIsSelfAdmin(0);
			userEntity.setFileTotal(0);
			userEntity.setGrain(0);
			userEntity.setRank(0);
			userEntity.setUploadSize(0);
			userEntity.setUploadTotal(0);
			userEntity.setIsDisabled(0);
			
			List<RoleEntity> roleList = new ArrayList<RoleEntity>();
			RoleEntity roleEntity = new RoleEntity();
			// 设置导入用户的默认角色
			Integer iRoleId = null;
			if("综合管理员".equals(roleNameCell.getContents().trim())) {
				iRoleId = Integer.valueOf(RoleEntity.ROLE_BB);
			} else if("三定管理员".equals(roleNameCell.getContents().trim())) {
				iRoleId = Integer.valueOf(RoleEntity.ROLE_BBBZGL);
			} else if("清单管理员".equals(roleNameCell.getContents().trim())) {
				iRoleId = Integer.valueOf(RoleEntity.ROLE_BBTGSG);
			} else if("信息查询人员".equals(roleNameCell.getContents().trim())) {
				iRoleId = Integer.valueOf(RoleEntity.ROLE_BBPT);
			}
			roleEntity.setRoleId(iRoleId);
			roleList.add(roleEntity);
			userEntity.setRoleList(roleList);
			
			userInfoVo.setUserEntity(userEntity);
			
			// **************用户区域信息实体**************
			userAreaEntity = new UserAreaEntity();
            userAreaEntity.setAreaId(UserUtils.getCurrentUser().getAreaId());
            userAreaEntity.setAreaCode(UserUtils.getCurrentUser().getAreaCode());
            userInfoVo.setUserAreaEntity(userAreaEntity);
            
            // **************用户私密信息实体**************
			ouserEntity = new OuserEntity();
			// 设置加密密码 初始密码定义常量
			ouserEntity.setPassword(DigestUtils.md5Hex(initPasswd));
			// 设置注册时间
			ouserEntity.setRegisterTime(new Date());
			// 设置注册用户IP
			ouserEntity.setRegisterIp(IpUtils.getRemoteAddr(request));
			ouserEntity.setLastLoginTime(new Date());
			ouserEntity.setLastLoginIp(initLastLoginIp);
			ouserEntity.setLoginCount(0);
			ouserEntity.setErrorCount(0);
			ouserEntity.setActivation(1);
			userInfoVo.setOuserEntity(ouserEntity);
			
			userInfoVoList.add(userInfoVo);
		}
		if(errorMap.get("error").size() > 0) {
			  resultInfo.setCode(ResultPojo.CODE_FAILURE);
	          resultInfo.setMsg("文件内容错误");
	       	  resultInfo.setResult(errorMap);
	       	  return resultInfo;
		}
		// 用户导入的数据为空场合
		if(userInfoVoList.size() == 0) {
			  resultInfo.setCode(ResultPojo.CODE_FAILURE);
	          resultInfo.setMsg("文件内容错误");
	       	  resultInfo.setResult("导入文件中的姓名、所属处（科）室和角色为空");
	       	  return resultInfo;
		}
		
		retUserInfoJson = userService.saveUserInfoList(userInfoVoList);
		// 判断保存是否成功失败
	    if (!ResultPojo.CODE_SUCCESS.equals(retUserInfoJson.getString("code")) ) {
			  // 保存失败场合
			  resultInfo.setCode(retUserInfoJson.getString("code"));
			  resultInfo.setMsg("[userService.saveOrUpdate] in function of cudImportUserInfoByExcel " + ResultPojo.MSG_FAILURE + "【"  + retUserInfoJson.getString("msg") + "】" );
			  resultInfo.setResult(retUserInfoJson.getJSONObject("result"));
		      return resultInfo;
		 }
	    
	    // 保存触发同步资源库表的信息(通过触发器方式调用资源库中的存储过程)
	    //userService.saveTriggerData(UserUtils.getCurrentUser().getId(), retUserInfoJson.getJSONObject("result").getString("cnt"));
		
         // 成功保存部门信息表和部门状态表返回
    	 return retUserInfoJson;
    	 
	}
	 
	/**
	 * 上传文件的检验
	 *
	 * @param file 校验文件
	 * @param maxVolumePram 文件最大限制
	 * @param nameMaxlengthPram 文件名称最大长度
	 * @param allowSuffixPram 文件后缀
	 * @return 返回文件check信息
	 */
	public String checkFileProperties(MultipartFile file, int maxVolumePram, int nameMaxlengthPram, String allowSuffixPram){
		// 文件最大限制
		if(maxVolumePram == 0){
			maxVolumePram = this.maxVolume;
		}

		// 文件名称最大长度
		if(nameMaxlengthPram == 0){
			nameMaxlengthPram = this.nameMaxlength;
		}

		// 文件后缀
		if(StringUtils.isEmpty(allowSuffixPram)){
			allowSuffixPram = this.allowSuffix;
		}

		// 文件为空Check
		if(null == file){
			return "上传文件为空！";
		}
		
		String origName = file.getOriginalFilename();

		// 上传非法文件Check
		if(origName.contains("../") || origName.contains("..\\")){
			return "上传的文件" + origName + "非法";
		}
		
		String ext = FilenameUtils.getExtension(origName).toLowerCase(Locale.ENGLISH);
		
		// 非允许的后缀Check
		if(!this.isAllowSuffix(ext,allowSuffixPram)){
			return ext + "格式的文件不允许上传";
		}

		// 超过附件大小限制
		if(!this.isAllowMaxFile((int) (file.getSize() / 1024), maxVolumePram)){
			return "您上传的文件" + origName + ",大于单文件大小限制" + maxVolumePram + "KB";
		}

		// 文件名长度限制
		if(origName.lastIndexOf('.') > nameMaxlengthPram){
			return "您上传的文件名不能超过" + nameMaxlengthPram + "个字";
		}

		return StringUtils.EMPTY;
	}

	/**
	 * 是否允许上传，根据文件大小
	 *
	 * @param size 文件大小，单位KB
	 * @param maxVolumeInt 文件允许大小，单位KB
	 * @return 判断文件是否符合大小限制
	 */
	private boolean isAllowMaxFile(int size, int maxVolumeInt){
		// 限制大小为0时，不做文件大小限制
		if(maxVolumeInt == 0){
			return true;
		}

		// 超出文件大小限制
		return maxVolumeInt >= size;
	}
	
	/**
	 * 检查文件后缀是否符合标准
	 *
	 * @param ext 上传文件后缀
	 * @param allowSuffixStr 文件后缀允许范围
	 * @return 返回后缀判断结果
	 */
	private boolean isAllowSuffix(String ext, String allowSuffixStr){
		// 文件后缀为空
		if(StringUtils.isBlank(ext)){
			return false;
		}
		// 后缀范围为空(没有后缀限制)
		if(StringUtils.isBlank(allowSuffixStr)){
			return true;
		}

		String[] as = allowSuffixStr.split(",");
		for(int i=0;i<as.length;i++){
			if(ext.equals(as[i])){
				return true;
			}
		}
		return false;
	}
}
